package cn.a592n.weightlibs.weight;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.view.animation.PathInterpolatorCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.DecelerateInterpolator;

/**
 * Created by Dizner on 2017/8/29.
 */

public class MPullView extends View {

    //初始化参数区域

    //画圆画笔
    private Paint mCirclePaint, mPointPaint, mSamllCirclePaint;
    //画贝塞尔曲线画笔
    private Paint mLinePaint;
    //圆半径
    private int mCircleRidus = 50;
    // 圆心点X坐标
    private float CirclePointX;
    // 圆心点Y坐标
    private float CirclePointY;
    //圆的颜色
    private int circleColor = 0xFFFF4081;
    //手指滑动进度
    private float mProgress;

    //最大绘制宽度
    private int mMaxWidth = 500;

    // 最大滑动高度
    private int mMaxHeight = 300;
    // 塞贝尔重心值
    private int mWeightValue = 50;

    //画贝塞尔曲线路径
    private Path mPath = new Path();
    //最大角度
    private int mMaxAngle = 80;

    // 粘性动画
    private ValueAnimator mValueAnimator;
    // 塞贝尔曲线控制点
    private Point leftEndPoint, rightEndPoint;
    // 当前滑动高度
    private float pregressHeight;

//    private Drawable mDrawableContent;

    // 刷新进度动画 的四个点坐标
    private float samllCirce1X;
    private float samllCirce2X;
    private float samllCirce3X;
    private float samllCirce4X;
    private float samllCirce1Y;
    private float samllCirce2Y;
    private float samllCirce3Y;
    private float samllCirce4Y;

    //刷新是否完成
    private boolean refreshFinish;
    //是否可以开始刷新动画
    private boolean canStartRefeash;
    //刷新完成来自用户操作
    private boolean finishedByUser;
    //    private int mDrawableContentMargin;
    public boolean isRefreashing;

    public MPullView(Context context) {
        super(context);
        init();
    }

    public MPullView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MPullView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public MPullView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        mCirclePaint = new Paint();
        //开启抗锯齿
        mCirclePaint.setAntiAlias(true);
        //开启抗抖动
        mCirclePaint.setDither(true);
        //设置画笔颜色
        mCirclePaint.setColor(circleColor);

        mLinePaint = new Paint();
        //开启抗锯齿
        mLinePaint.setAntiAlias(true);
        //开启抗抖动
        mLinePaint.setDither(true);
        //设置画笔颜色
        mLinePaint.setColor(circleColor);

        mPointPaint = new Paint();
        mPointPaint.setStrokeWidth(10);
        //开启抗锯齿
        mPointPaint.setAntiAlias(true);
        //开启抗抖动
        mPointPaint.setDither(true);
        //设置画笔颜色
        mPointPaint.setColor(Color.GREEN);

        mSamllCirclePaint = new Paint();
        mSamllCirclePaint.setStrokeWidth(10);
        //开启抗锯齿
        mSamllCirclePaint.setAntiAlias(true);
        //开启抗抖动
        mSamllCirclePaint.setDither(true);
        //设置画笔颜色
        mSamllCirclePaint.setColor(Color.GREEN);

    }

    /**
     * 开始粘性动画
     */
    public void startAnimator() {
        //滑动高度大于0才可以执行动画
//        if (getHeight() > 0) {
        if (mValueAnimator == null) {
            mValueAnimator = ValueAnimator.ofFloat(mProgress, 0f);
            mValueAnimator.setDuration(500);
            mValueAnimator.setInterpolator(new DecelerateInterpolator());
            mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    Object value = valueAnimator.getAnimatedValue();
                    if (value instanceof Float) {
                        setmProgress((Float) value);
                    }
                }
            });
            mValueAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animator) {

                }

                @Override
                public void onAnimationEnd(Animator animator) {
                    //在动画完成后初始化一些参数
                    initStat();
                }

                @Override
                public void onAnimationCancel(Animator animator) {

                }

                @Override
                public void onAnimationRepeat(Animator animator) {

                }
            });
        } else {
            if (mValueAnimator.isRunning()) {
                mValueAnimator.cancel();
            }
            mValueAnimator.setFloatValues(mProgress, 0f);
        }

        mValueAnimator.start();
//        }

    }


    /**
     * 初始化一些状态
     */
    private void initStat() {
        Log.d("PROGRESS_IO", "刷新初始化————————");
        canStartRefeash = false;
        refreshFinish = false;
        finishedByUser = false;
        isRefreashing = false;
//        postInvalidate();
    }

    /**
     * 刷新完成后调用此方法关闭动画
     *
     * @param refreshFinish
     */
    public void setRefreshFinish(boolean refreshFinish) {
        if (isRefreashing)
            this.refreshFinish = refreshFinish;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int initMeasurWidth = mCircleRidus * 2 + getPaddingLeft() + getPaddingRight();
        int initMeasurHeight = (int) ((mMaxHeight * mProgress + 0.5f) + getPaddingBottom() + getPaddingTop());


        int measureWidth = 0;
        int measureHeight = 0;


        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        switch (widthMode) {
            //最大
            case MeasureSpec.AT_MOST:
                measureWidth = Math.min(width, initMeasurWidth);
                break;
            //确定值
            case MeasureSpec.EXACTLY:
                measureWidth = width;
                break;
            //不确定
            case MeasureSpec.UNSPECIFIED:
                measureWidth = initMeasurWidth;
                break;
        }

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        switch (heightMode) {
            //最大
            case MeasureSpec.AT_MOST:
                measureHeight = Math.min(height, initMeasurHeight);
                break;
            //确定值
            case MeasureSpec.EXACTLY:
                measureHeight = height;
                break;
            //不确定
            case MeasureSpec.UNSPECIFIED:
                measureHeight = initMeasurHeight;
                break;
        }
        setMeasuredDimension(measureWidth, measureHeight);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 在布局大小改变时重新进行布局测量绘制等一系列操作
        Log.d("TTTYYYUUU", " w: " + w + " h: " + h + " oldw: " + oldw + " oldh: " + oldh);
        //当布局开始向上闭合时调用
        if (oldh > h) {
            canStartRefeash = false;
            finishedByUser = true;
            Log.d("TTTYYYUUU", "开始向上");
//            if (!mValueAnimator.isRunning()) {
//                startAnimator();
//            }
            if (h <= 0.6) {
                //到达最顶部进行初始化
                initStat();
            }
        }
        updateView();
    }


    /**
     * 根据手指滑动进度更新界面
     */
    private void updateView() {

        float xProgress = new DecelerateInterpolator().getInterpolation(mProgress);


        float w = calculateValue(getWidth(), mMaxWidth, mProgress);
        float h = calculateValue(0, mMaxHeight, mProgress);

        pregressHeight = w;
        //圆心X
        CirclePointX = w / 2;
        //圆心Y
        CirclePointY = h - mCircleRidus;

        //结束点
        float leftEndPointX, leftEndPointY;
        //控制点
        float leftControlPointX, leftControlPointY;
        //此处用到路径差值器
        double radian = Math.toRadians(mMaxAngle * PathInterpolatorCompat.create((mCircleRidus * 2) / mMaxHeight, 90.0f / mMaxAngle).getInterpolation(xProgress));
        float x = (float) (Math.sin(radian) * mCircleRidus);
        float y = (float) (Math.cos(radian) * mCircleRidus);

        leftEndPointX = CirclePointX - x;

        leftEndPointY = CirclePointY + y;


        leftControlPointY = calculateValue(0, mWeightValue, xProgress);

        float tmpHeight = leftEndPointY - leftControlPointY;

        leftControlPointX = (float) (leftEndPointX - tmpHeight / Math.tan(radian));
        //右侧点计算
        float rightEndPointX = CirclePointX + CirclePointX - leftEndPointX;
        float rightEndPointY = leftEndPointY;
        float rightControlPointX = CirclePointX + CirclePointX - leftControlPointX, rightControlPointY = leftControlPointY;


        leftEndPoint = new Point((int) leftControlPointX, (int) leftControlPointY);
        rightEndPoint = new Point((int) rightControlPointX, (int) rightControlPointY);

//        updateDrawableContent(CirclePointX, CirclePointY, mCircleRidus);

        // 路径重置
        mPath.reset();
        mPath.moveTo(0, 0);
        // 添加左侧塞贝尔曲线路径
        mPath.quadTo(leftControlPointX, leftControlPointY, leftEndPointX, leftEndPointY);
        // 画线至右侧
        mPath.lineTo(rightEndPointX, rightEndPointY);
        // 添加右侧塞贝尔曲线路径
        mPath.quadTo(rightControlPointX, rightControlPointY, w, 0);


    }


//    /**
//     * 更新圆部分的内容
//     *
//     * @param circlePointX
//     * @param circlePointY
//     * @param mCircleRidus
//     */
//    private void updateDrawableContent(float circlePointX, float circlePointY, int mCircleRidus) {
//        if (mDrawableContent != null) {
//            int left = (int) (circlePointX - mCircleRidus + mDrawableContentMargin);
//            int right = (int) (circlePointX + mCircleRidus - mDrawableContentMargin);
//            int top = (int) (circlePointY - mCircleRidus + mDrawableContentMargin);
//            int bottom = (int) (circlePointY + mCircleRidus - mDrawableContentMargin);
//            mDrawableContent.setBounds(left, right, top, bottom);
//        }
//    }

//    public void setDrawableContent(Drawable mDrawableContent) {
//        this.mDrawableContent = mDrawableContent;
//        postInvalidate();
//    }

//    public void setDrawableContentMargin(int mDrawableContentMargin) {
//        this.mDrawableContentMargin = mDrawableContentMargin;
//        postInvalidate();
//    }

    /**
     * 开始刷新动画
     */
    public void startRefeash() {
        try {
            if (!isRefreashing) {
                if (mProgress >= 0.9f) {
                    //滑动到达指定位置后开始绘制刷新进度动画
//                if (mProgress > 0.9)
//                    setmProgress(0.8f);
                    canStartRefeash = true;
                    new Thread() {
                        @Override
                        public void run() {
                            for (float i = 0; ; i += 0.01) {
                                // 实时获取角度变化
                                double radians = Math.toRadians(calculateValue(0, 360, i));
                                //实时改变五个圆的圆心位置
                                samllCirce1X = (float) ((mCircleRidus - 25) * Math.cos(radians)) + CirclePointX;
                                samllCirce1Y = (float) ((mCircleRidus - 25) * Math.sin(radians)) + CirclePointY;
                                samllCirce2X = (float) ((mCircleRidus - 25) * Math.cos(radians - 0.8)) + CirclePointX;
                                samllCirce2Y = (float) ((mCircleRidus - 25) * Math.sin(radians - 0.8)) + CirclePointY;
                                samllCirce3X = (float) ((mCircleRidus - 25) * Math.cos(radians - 1.4)) + CirclePointX;
                                samllCirce3Y = (float) ((mCircleRidus - 25) * Math.sin(radians - 1.4)) + CirclePointY;
                                samllCirce4X = (float) ((mCircleRidus - 25) * Math.cos(radians - 2.0)) + CirclePointX;
                                samllCirce4Y = (float) ((mCircleRidus - 25) * Math.sin(radians - 2.0)) + CirclePointY;
                                //重绘
                                isRefreashing = true;
                                postInvalidate();
                                try {
                                    // 调整速度
                                    Thread.sleep(20);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }

                                if (finishedByUser) {
                                    break;
                                }

                                if (refreshFinish) {
                                    post(new Runnable() {
                                        @Override
                                        public void run() {
                                            //在完成刷新后调用关闭动画
                                            startAnimator();
                                        }
                                    });
                                    break;
                                }
                            }
                        }
                    }.start();
                } else {
                    startAnimator();
                }
            } else {
                //处理手指抬起后的事件，在此判断如果用户执行在刷新时执行上划动作开启关闭动画
//                Log.d("THGFLL", mProgress + "");
                if (getHeight() > 0 && !touchUp) {
                    startAnimator();
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int count = canvas.save();
        //初始坐标系处理
        float tranx = (getWidth() - calculateValue(getWidth(), mMaxWidth, mProgress)) / 2;

        canvas.translate(tranx, 0);
        //绘制赛贝尔曲线
        canvas.drawPath(mPath, mLinePaint);
        //绘制圆
        canvas.drawCircle(CirclePointX, CirclePointY, mCircleRidus, mCirclePaint);

        //绘制赛贝尔曲线控制点--左
//        canvas.drawPoint(leftEndPoint.x, leftEndPoint.y, mPointPaint);
        //绘制赛贝尔曲线控制点--右
//        canvas.drawPoint(rightEndPoint.x, rightEndPoint.y, mPointPaint);
        mPointPaint.setColor(Color.WHITE);
        canvas.drawCircle(CirclePointX, CirclePointY, mCircleRidus - 10, mPointPaint);

        if (canStartRefeash) {
            // 可以加载刷新动画时，开始绘制四个小点
            canvas.drawCircle(samllCirce1X, samllCirce1Y, 8, mSamllCirclePaint);
            canvas.drawCircle(samllCirce2X, samllCirce2Y, 6, mSamllCirclePaint);
            canvas.drawCircle(samllCirce3X, samllCirce3Y, 4, mSamllCirclePaint);
            canvas.drawCircle(samllCirce4X, samllCirce4Y, 2, mSamllCirclePaint);
        }


//        try {
//            if (mDrawableContent != null) {
////                Log.d("YYYYYYYIIIII", mDrawableContent.getBounds().bottom + "");
//                canvas.save();
//                canvas.clipRect(mDrawableContent.getBounds());
//                mDrawableContent.draw(canvas);
//                canvas.restore();
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }


        canvas.restoreToCount(count);

    }


    private boolean touchUp;

    /**
     * 设置手指滑动进度,传入动作判断
     *
     * @param mProgress
     */
    public void setmProgress(float mProgress, boolean isUp) {
        this.touchUp = isUp;
        if (isUp) {
            this.mProgress = mProgress;
            requestLayout();
        } else {
            this.mProgress = mProgress + 1;
            requestLayout();
        }

        Log.d("TAG_PP", "进度：" + this.mProgress);
        // 距离更新,重新测量
    }

    /**
     * 设置手指滑动进度
     *
     * @param mProgress
     */
    public void setmProgress(float mProgress) {
        if (mProgress > 0) {
            this.mProgress = mProgress;
            requestLayout();
        } else {
            initStat();
        }
        Log.d("TAG_PP", "进度：" + mProgress);
        // 距离更新,重新测量
    }


    /**
     * 根据进度计算相应值得变化值
     *
     * @param start
     * @param end
     * @param progress
     * @return
     */
    public float calculateValue(int start, int end, float progress) {
        return start + (end - start) * progress;
    }
}
